bitkeeper revision 1.999 (40d83983YNm1foUR4ODZt9AAVdci-Q)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Tue, 22 Jun 2004 13:52:03 +0000 (13:52 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Tue, 22 Jun 2004 13:52:03 +0000 (13:52 +0000)
Switch to new method of shutting down domains.

.rootkeys
tools/xenmgr/lib/XendDomain.py
tools/xenmgr/lib/XendDomainInfo.py
tools/xenmgr/lib/server/SrvConsoleServer.py
tools/xenmgr/lib/server/SrvDomain.py
tools/xenmgr/lib/server/channel.py
tools/xenmgr/lib/server/controller.py
tools/xenmgr/lib/server/domain.py [new file with mode: 0644]
tools/xenmgr/lib/server/messages.py
tools/xenmgr/lib/xm/create.py
tools/xenmgr/lib/xm/shutdown.py

index be37c85b90317bde5b70f6bc1219184da332b403..fe4c4ae455929ce89f711fd01d526d8be6b965f3 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40c9c469hJ_IlatRne-9QEa0-wlquw tools/xenmgr/lib/server/console.py
 40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/xenmgr/lib/server/controller.py
 40c9c469vHh-qLiiubdbKEQbJf18Zw tools/xenmgr/lib/server/cstruct.py
+40d83983OXjt-y3HjSCcuoPp9rzvmw tools/xenmgr/lib/server/domain.py
 40c9c469yrm31i60pGKslTi2Zgpotg tools/xenmgr/lib/server/messages.py
 40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/xenmgr/lib/server/netif.py
 40c9c469ZqILEQ8x6yWy0_51jopiCg tools/xenmgr/lib/server/params.py
index e37cb5d05c20d545833a672d37b3099ebc8565f5..d3cddc4e7582d0177e3fe1eb5285a611d8c9cbe3 100644 (file)
@@ -203,21 +203,22 @@ class XendDomain:
         """Pause domain execution.
         """
         dom = int(id)
+        eserver.inject('xend.domain.pause', id)
         return xc.domain_pause(dom=dom)
     
-    def domain_shutdown(self, id):
+    def domain_shutdown(self, id, reason='poweroff'):
         """Shutdown domain (nicely).
         """
         dom = int(id)
         if dom <= 0:
             return 0
-        eserver.inject('xend.domain.shutdown', id)
-        val = xc.domain_destroy(dom=dom) # FIXME -- send CMSG_SHUTDOWN
+        eserver.inject('xend.domain.shutdown', [id, reason])
+        val = xend.domain_shutdown(dom, reason)
         self.refresh()
         return val
     
     def domain_halt(self, id):
-        """Shutdown domain immediately.
+        """Terminate domain immediately.
         """
         dom = int(id)
         if dom <= 0:
index 8283584f3872030d129615dfe49e46745d7659f2..88598cd9c62299e3337a8e599441ccd584e582c1 100644 (file)
@@ -122,8 +122,12 @@ class XendDomainInfo:
             susp  = (self.info['shutdown'] and 's') or '-'
             crash = (self.info['crashed'] and 'c') or '-'
             state = run + block + stop + susp + crash
-            sxpr.append(['cpu', self.info['cpu']])
             sxpr.append(['state', state])
+            if self.info['shutdown']:
+                reasons = ["poweroff", "reboot", "suspend"]
+                reason = reasons[info['shutdown_reason']]
+                sxpr.append(['shutdown_reason', reason])
+            sxpr.append(['cpu', self.info['cpu']])
             sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
         if self.console:
             sxpr.append(self.console.sxpr())
index 6059ef2ebf015e291374f511987fd6c3d1df5c37..21d39140b25b35be84476c0c37a1dc49aec96605 100644 (file)
@@ -36,6 +36,7 @@ import channel
 import blkif
 import netif
 import console
+import domain
 from params import *
 
 DEBUG = 1
@@ -408,6 +409,16 @@ class EventFactory(protocol.Factory):
         proto.factory = self
         return proto
 
+class VirqClient:
+    def __init__(self, daemon):
+        self.daemon = daemon
+
+    def virqReceived(self, virq):
+        print 'VirqClient.virqReceived>', virq
+
+    def lostChannel(self, channel):
+        print 'VirqClient.lostChannel>', channel
+        
 class Daemon:
     """The xend daemon.
     """
@@ -537,11 +548,13 @@ class Daemon:
         self.listenMgmt()
         self.listenEvent()
         self.listenNotifier()
+        self.listenVirq()
         SrvServer.create()
         reactor.run()
 
     def createFactories(self):
         self.channelF = channel.channelFactory()
+        self.domainCF = domain.DomainControllerFactory()
         self.blkifCF = blkif.BlkifControllerFactory()
         self.netifCF = netif.NetifControllerFactory()
         self.consoleCF = console.ConsoleControllerFactory()
@@ -563,6 +576,10 @@ class Daemon:
         p.startListening()
         return p
 
+    def listenVirq(self):
+        virqChan = self.channelF.virqChannel(channel.VIRQ_DOM_EXC)
+        virqChan.registerClient(VirqClient(self))
+
     def exit(self):
         reactor.diconnectAll()
         sys.exit(0)
@@ -650,28 +667,15 @@ class Daemon:
         if console.conn:
             console.conn.loseConnection()
 
-    def domain_start(self, id):
-        """Start domain running.
+    def domain_shutdown(self, dom, reason):
+        """Shutdown a domain.
         """
-        dom = int(id)
-        if dom <= 0: return 0
-        return xc.domain_start(dom=dom)
+        ctrl = self.domainCF.getInstanceByDom(dom)
+        if not ctrl:
+            raise ValueError('No domain controller: %d' % dom)
+        ctrl.shutdown(reason)
+        return 0
         
-    def domain_stop(self, id):
-        """Stop domain running.
-        """
-        dom = int(id)
-        if dom <= 0: return 0 
-        xc.domain_stop(dom=dom)
-
-    def domain_destroy(self, id, force=0):
-        """Destroy a domain. Shutdown if force=0, terminate immediately if force=1.
-        """
-        dom = int(id)
-        if dom <= 0: return 0 
-        return xc.domain_destroy(dom=dom, force=force)
-    
-
 def instance():
     global inst
     try:
index 07d3cfa7dea05fbe20253f0e5b28dfa326352be5..5034869e63c489e1e9932bfbfaa13c8d588babb4 100644 (file)
@@ -193,8 +193,8 @@ class SrvDomain(SrvDir):
 
     def form(self, req):
         req.write('<form method="post" action="%s">' % req.prePathURL())
-        req.write('<input type="submit" name="op" value="start">')
-        req.write('<input type="submit" name="op" value="stop">')
+        req.write('<input type="submit" name="op" value="unpause">')
+        req.write('<input type="submit" name="op" value="pause">')
         req.write('<input type="submit" name="op" value="shutdown">')
         req.write('<input type="submit" name="op" value="halt">')
         req.write('<br><input type="submit" name="op" value="migrate">')
index 130d23254f35fb43b20abf79d83fbae36aec5a82..3f2a7a63825f71cda69c5e0ee7d7f38971ed2476 100755 (executable)
@@ -2,6 +2,12 @@ import Xc; xc = Xc.new()
 import xend.utils
 from messages import msgTypeName
 
+VIRQ_MISDIRECT  = 0  # Catch-all interrupt for unbound VIRQs.
+VIRQ_TIMER      = 1  # Timebase update, and/or requested timeout.
+VIRQ_DEBUG      = 2  # Request guest to dump debug info.
+VIRQ_CONSOLE    = 3  # (DOM0) bytes received on emergency console.
+VIRQ_DOM_EXC    = 4  # (DOM0) Exceptional event for some domain.
+
 def eventChannel(dom1, dom2):
     return xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2)
 
@@ -143,7 +149,7 @@ class VirqChannel(BaseChannel):
         self.virq = virq
         # Notification port (int).
         self.port = xc.evtchn_bind_virq(virq)
-        self.idx = port
+        self.idx = self.port
         # Clients to call when a virq arrives.
         self.clients = []
 
index 23b0f7fde1e722fd973564d0e27634f79b029dd8..791e987511d4b25b3da971885b7d1bf5b8b00b69 100755 (executable)
@@ -36,12 +36,14 @@ class CtrlMsgRcvr:
         pass
     
     def registerChannel(self):
+        print 'CtrlMsgRcvr>registerChannel>', self
         self.channel = self.channelFactory.domChannel(self.dom)
         self.idx = self.channel.getIndex()
         if self.majorTypes:
             self.channel.registerDevice(self.majorTypes, self)
         
     def deregisterChannel(self):
+        print 'CtrlMsgRcvr>deregisterChannel>', self
         if self.channel:
             self.channel.deregisterDevice(self)
             del self.channel
@@ -71,6 +73,8 @@ class ControllerFactory(CtrlMsgRcvr):
         self.instances = {}
         self.dlist = []
         self.dom = 0
+        # Timeout (in seconds) for deferreds.
+        self.timeout = 10
         
     def addInstance(self, instance):
         self.instances[instance.idx] = instance
@@ -99,6 +103,9 @@ class ControllerFactory(CtrlMsgRcvr):
 
     def addDeferred(self):
         d = defer.Deferred()
+        if self.timeout > 0:
+            # The deferred will error if not called before timeout.
+            d.setTimeout(self.timeout)
         self.dlist.append(d)
         return d
 
diff --git a/tools/xenmgr/lib/server/domain.py b/tools/xenmgr/lib/server/domain.py
new file mode 100644 (file)
index 0000000..ab22234
--- /dev/null
@@ -0,0 +1,41 @@
+import channel
+import controller
+from messages import *
+
+class DomainControllerFactory(controller.ControllerFactory):
+    """Factory for creating domain controllers.
+    """
+
+    def createInstance(self, dom):
+        d = DomainController(self, dom)
+        self.addInstance(d)
+        return d
+    
+    def getInstanceByDom(self, dom):
+        for inst in self.instances.values():
+            if inst.dom == dom:
+                return inst
+        inst = self.createInstance(dom)
+        return inst
+
+
+class DomainController(controller.Controller):
+    """Generic controller for a domain.
+    """
+
+    reasons = {'poweroff' : 'shutdown_poweroff_t',
+               'reboot'   : 'shutdown_reboot_t',
+               'suspend'  : 'shutdown_suspend_t' }
+
+    def __init__(self, factory, dom):
+        controller.Controller.__init__(self, factory, dom)
+        self.majorTypes = [ CMSG_SHUTDOWN ]
+        self.registerChannel()
+        print 'DomainController>', self, self.channel, self.idx
+
+    def shutdown(self, reason):
+        msgtype = self.reasons.get(reason)
+        if not msgtype:
+            raise ValueError('invalid reason:' + reason)
+        msg = packMsg(msgtype, {})
+        self.writeRequest(msg)
index 649629105c528cd56419031aa015d54f3598121a..78bc24526f201675d74169516829e5c6aff014e1 100644 (file)
@@ -16,7 +16,7 @@ msg_formats = {}
 
 CMSG_CONSOLE  = 0
 
-console_formats = { 'console_data': (CMSG_CONSOLE, 0, "?") }
+console_formats = { 'console_data': (CMSG_CONSOLE, 0) }
 
 msg_formats.update(console_formats)
 
@@ -62,28 +62,28 @@ BLKIF_BE_STATUS_MAPPING_ERROR       = 9
 
 blkif_formats = {
     'blkif_be_connect_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT, "QIILI"),
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
 
     'blkif_be_create_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE, "QII"),
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
 
     'blkif_be_destroy_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY, "QII"),
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
 
     'blkif_be_vbd_create_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE, "QIHII"),
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
 
     'blkif_be_vbd_grow_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW , "QIHHHQQI"),
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW),
 
     'blkif_fe_interface_status_changed_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED, "III"),
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED),
 
     'blkif_fe_driver_status_changed_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED, "?"),
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED),
 
     'blkif_fe_interface_connect_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT, "IL"),
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
 }
 
 msg_formats.update(blkif_formats)
@@ -115,59 +115,55 @@ NETIF_DRIVER_STATUS_UP     = 1
 
 netif_formats = {
     'netif_be_connect_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT, "QIILLI"),
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT),
 
     'netif_be_create_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE, "QIBBBBBBBBI"),
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE),
 
     'netif_be_destroy_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY, "QII"),
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
 
     'netif_be_disconnect_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT, "QII"),
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT),
 
     'netif_be_driver_status_changed_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED, "QII"),
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED),
 
     'netif_fe_driver_status_changed_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED, "II"),
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED),
 
     'netif_fe_interface_connect_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT, "ILL"),
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
 
     'netif_fe_interface_status_changed_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, "IIIBBBBBBBB"),
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED),
     }
 
 msg_formats.update(netif_formats)
 
 #============================================================================
-CMSG_SUSPEND  = 5
 CMSG_SHUTDOWN = 6
 
-CMSG_SHUTDOWN_HALT      = 0
-CMSG_SHUTDOWN_POWEROFF  = 1
-CMSG_SHUTDOWN_REBOOT    = 2
+CMSG_SHUTDOWN_POWEROFF  = 0
+CMSG_SHUTDOWN_REBOOT    = 1
+CMSG_SHUTDOWN_SUSPEND   = 2
 
 STOPCODE_shutdown       = 0
 STOPCODE_reboot         = 1
 STOPCODE_suspend        = 2
 
-ctrlif_formats = {
-    'ctrlif_suspend_t':
-    (CMSG_SUSPEND, 0, "??"),
-
-    'ctrlif_shutdown_halt_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_HALT, "??"),
-    
-    'ctrlif_shutdown_poweroff_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF, "??"),
+shutdown_formats = {
+    'shutdown_poweroff_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF),
     
-    'ctrlif_shutdown_reboot_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT, "??"),
+    'shutdown_reboot_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT),
+
+    'shutdown_suspend_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
     }
 
-msg_formats.update(ctrlif_formats)
+msg_formats.update(shutdown_formats)
 
 #============================================================================
 
@@ -176,7 +172,7 @@ class Msg:
 
 def packMsg(ty, params):
     if DEBUG: print '>packMsg', ty, params
-    (major, minor, packing) = msg_formats[ty]
+    (major, minor) = msg_formats[ty]
     args = {}
     for (k, v) in params.items():
         if k == 'mac':
index a365424acf31f4efac482808096d1eaafa15f1b2..29b4c7b6dcb553835865567ffea8fe265c05ebc4 100644 (file)
@@ -235,7 +235,7 @@ def preprocess_ip(opts):
     setip = (opts.hostname or opts.netmask
              or opts.gateway or opts.dhcp or opts.interface)
     if not setip: return
-    if not opts
+    #if not opts
     ip = (opts.ip
           + ':'
           + ':' + opts.gateway
index 8c7a517e96d195b17c7b9c38768ccf067ae1165b..0108a8df0ffcda6dafa0bf3af0b35167b0e2dd71 100644 (file)
@@ -10,7 +10,7 @@ gopts = Opts(use="""[options] [DOM]
 Shutdown one or more domains gracefully.""")
 
 gopts.opt('help', short='h',
-         fn=set_value, default=0,
+         fn=set_true, default=0,
          use="Print this help.")
 
 gopts.opt('all', short='a',
@@ -46,8 +46,8 @@ def main_all(opts, args):
     shutdown(opts, None, opts.wait)
 
 def main_dom(opts, args):
-    if len(args) < 2: opts.err('Missing domain')
-    dom = argv[1]
+    if len(args) < 1: opts.err('Missing domain')
+    dom = args[0]
     try:
         domid = int(dom)
     except:
@@ -59,6 +59,8 @@ def main(argv):
     args = opts.parse(argv)
     if opts.help:
         opts.usage()
+        return
+    print 'shutdown.main>', len(args), args
     if opts.all:
         main_all(opts, args)
     else: